const path = require('path');
const fs = require('fs');
const { ensureDirExists } = require('./helpers');

// 分片临时存储目录
const CHUNK_DIR = path.join(__dirname, '../uploads/chunks');
ensureDirExists(CHUNK_DIR);

/**
 * 保存分片文件
 * @param {string} fileIdentifier 文件唯一标识
 * @param {number} chunkIndex 分片索引
 * @param {Buffer} chunkData 分片数据
 * @returns {Promise<string>} 分片文件路径
 */
const saveChunk = (fileIdentifier, chunkIndex, chunkData) => {
  return new Promise((resolve, reject) => {
    const chunkDir = path.join(CHUNK_DIR, fileIdentifier);
    ensureDirExists(chunkDir);
    
    const chunkPath = path.join(chunkDir, `chunk_${chunkIndex}`);
    
    fs.writeFile(chunkPath, chunkData, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve(chunkPath);
      }
    });
  });
};

/**
 * 检查分片是否存在
 * @param {string} fileIdentifier 文件唯一标识
 * @param {number} chunkIndex 分片索引
 * @returns {boolean}
 */
const chunkExists = (fileIdentifier, chunkIndex) => {
  const chunkDir = path.join(CHUNK_DIR, fileIdentifier);
  const chunkPath = path.join(chunkDir, `chunk_${chunkIndex}`);
  return fs.existsSync(chunkPath);
};

/**
 * 获取已上传的分片列表
 * @param {string} fileIdentifier 文件唯一标识
 * @returns {Promise<number[]>} 已上传的分片索引数组
 */
const getUploadedChunks = (fileIdentifier) => {
  return new Promise((resolve, reject) => {
    const chunkDir = path.join(CHUNK_DIR, fileIdentifier);
    
    if (!fs.existsSync(chunkDir)) {
      return resolve([]);
    }
    
    fs.readdir(chunkDir, (err, files) => {
      if (err) {
        reject(err);
      } else {
        // 提取分片索引：chunk_0, chunk_1 -> [0, 1]
        const chunks = files
          .filter(file => file.startsWith('chunk_'))
          .map(file => parseInt(file.replace('chunk_', '')))
          .filter(index => !isNaN(index))
          .sort((a, b) => a - b);
        
        resolve(chunks);
      }
    });
  });
};

/**
 * 合并分片文件
 * @param {string} fileIdentifier 文件唯一标识
 * @param {string} outputPath 输出文件路径
 * @param {number} totalChunks 总分片数
 * @returns {Promise<string>} 合并后的文件路径
 */
const mergeChunks = (fileIdentifier, outputPath, totalChunks) => {
  return new Promise((resolve, reject) => {
    const chunkDir = path.join(CHUNK_DIR, fileIdentifier);
    const writeStream = fs.createWriteStream(outputPath);
    
    let currentChunk = 0;
    let writtenChunks = 0;
    
    const writeNextChunk = () => {
      if (currentChunk >= totalChunks) {
        // 所有分片写入完成，关闭流
        writeStream.end();
        return;
      }
      
      const chunkPath = path.join(chunkDir, `chunk_${currentChunk}`);
      
      fs.readFile(chunkPath, (err, data) => {
        if (err) {
          writeStream.destroy();
          reject(new Error(`读取分片 ${currentChunk} 失败: ${err.message}`));
        } else {
          writeStream.write(data, (writeErr) => {
            if (writeErr) {
              writeStream.destroy();
              reject(new Error(`写入分片 ${currentChunk} 失败: ${writeErr.message}`));
            } else {
              writtenChunks++;
              currentChunk++;
              
              // 继续写入下一个分片
              writeNextChunk();
            }
          });
        }
      });
    };
    
    writeStream.on('finish', () => {
      // 合并完成后，删除分片目录
      deleteChunkDir(fileIdentifier)
        .then(() => resolve(outputPath))
        .catch(reject);
    });
    
    writeStream.on('error', (err) => {
      reject(err);
    });
    
    // 开始写入
    writeNextChunk();
  });
};

/**
 * 删除分片目录
 * @param {string} fileIdentifier 文件唯一标识
 * @returns {Promise<void>}
 */
const deleteChunkDir = (fileIdentifier) => {
  return new Promise((resolve, reject) => {
    const chunkDir = path.join(CHUNK_DIR, fileIdentifier);
    
    if (!fs.existsSync(chunkDir)) {
      return resolve();
    }
    
    fs.readdir(chunkDir, (err, files) => {
      if (err) {
        reject(err);
      } else {
        const deletePromises = files.map(file => {
          const filePath = path.join(chunkDir, file);
          return new Promise((res, rej) => {
            fs.unlink(filePath, (unlinkErr) => {
              if (unlinkErr) rej(unlinkErr);
              else res();
            });
          });
        });
        
        Promise.all(deletePromises)
          .then(() => fs.rmdir(chunkDir, (rmdirErr) => {
            if (rmdirErr) reject(rmdirErr);
            else resolve();
          }))
          .catch(reject);
      }
    });
  });
};

/**
 * 清理过期的分片文件（超过24小时的）
 * @returns {Promise<void>}
 */
const cleanExpiredChunks = () => {
  return new Promise((resolve, reject) => {
    fs.readdir(CHUNK_DIR, (err, dirs) => {
      if (err) {
        return reject(err);
      }
      
      const now = Date.now();
      const oneDay = 24 * 60 * 60 * 1000; // 24小时
      
      const cleanPromises = dirs.map(dir => {
        const dirPath = path.join(CHUNK_DIR, dir);
        
        return new Promise((res) => {
          fs.stat(dirPath, (statErr, stats) => {
            if (!statErr && stats.isDirectory()) {
              const age = now - stats.mtime.getTime();
              if (age > oneDay) {
                // 删除过期目录
                deleteChunkDir(dir)
                  .then(() => {
                    console.log(`已清理过期分片目录: ${dir}`);
                    res();
                  })
                  .catch(() => res());
              } else {
                res();
              }
            } else {
              res();
            }
          });
        });
      });
      
      Promise.all(cleanPromises)
        .then(() => resolve())
        .catch(reject);
    });
  });
};

module.exports = {
  saveChunk,
  chunkExists,
  getUploadedChunks,
  mergeChunks,
  deleteChunkDir,
  cleanExpiredChunks
};

